package org.entities;

import org.BlockMap;
import org.GameState;
import org.Progress;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Animation;
import org.newdawn.slick.Image;
import org.newdawn.slick.Sound;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.SlickException;
//import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Polygon;
import org.entities.Shoot;


public class Marine extends LevelObject {


    public static final float MOVE_SPEED=0.05f;
    private float dx=0;
    private float dy=0;
    public Polygon fieldOfVision,fieldOfVision2; 
    public boolean attack,onGround;
    private static int size[]={10,2,40,2,40,50,10,50};	// marine dimensions
    //private boolean animLimiter;
    private int currentShootTime=0;	// bullet frequency counter
    private int maxShootTime=800;	    // time before next shoot
    private boolean nextShootOK;	    // checks if next shoot can be fired
    public Shoot bullet,bullet1;
    private Sound baseShot,dieSound,hitSound;
    public Image marineShoot;
    public Animation 
    marineStand,
    marineLeft,
    marineRight,
    attackLeft,
    attackRight,
    hurtLeft,
    hurtRight,
    fallback;

    public Marine(int x, int y, String type) throws SlickException {

        // ==========================
        // create marine bounding box
        // ==========================
        super(x, y,
                x+size[0],y+size[1],
                x+size[2],y+size[3],
                x+size[4],y+size[5],
                x+size[6],y+size[7],
                type);

        // ===========
        // shields
        // ===========

        MAX_SHIELDS = 30;
        shields = MAX_SHIELDS;    // init marine HP



        // =========================== 
        // create marine animations
        // ===========================

        SpriteSheet sheet = new SpriteSheet("data/anim/marine.png",48,48);

        fallback = new Animation();
        for (int frame=0;frame<6;frame++) {
            fallback.addFrame(sheet.getSprite(frame,4), 180);
        }
        marineStand = new Animation();
        for (int frame=0;frame<6;frame++) {
            marineStand.addFrame(sheet.getSprite(frame,4), 180);
        }
        marineLeft = new Animation();
        for (int frame=0;frame<8;frame++) {
            marineLeft.addFrame(sheet.getSprite(frame,1), 180);
        }
        marineRight = new Animation();
        for (int frame=0;frame<8;frame++) {
            marineRight.addFrame(sheet.getSprite(frame,0), 180);
        }
        attackRight = new Animation();
        for (int frame=0;frame<1;frame++) {
            attackRight.addFrame(sheet.getSprite(frame,2), 180);
        }
        attackLeft = new Animation();
        for (int frame=0;frame<1;frame++) {
            attackLeft.addFrame(sheet.getSprite(frame,3), 180);
        }
        hurtRight = new Animation();
        for (int frame=0;frame<3;frame++) {
            hurtRight.addFrame(sheet.getSprite(frame,5), 300);
        }
        hurtLeft = new Animation();
        for (int frame=0;frame<3;frame++) {
            hurtLeft.addFrame(sheet.getSprite(frame,6), 300);
        }

        fallback.setAutoUpdate(false);
        marineStand.setAutoUpdate(false);
        marineLeft.setAutoUpdate(false);
        marineRight.setAutoUpdate(false);


        // =============================
        // create polygon for marine fov
        // =============================

        fieldOfVision=new Polygon(new float[]{				
                size[0]-160,size[1],
                size[2]+160,size[3],
                size[4]+160,size[5],
                size[6]-160,size[7]});
        fieldOfVision2=new Polygon(new float[]{              
                size[0]-240,size[1],
                size[2]+240,size[3],
                size[4]+240,size[5],
                size[6]-240,size[7]});

        marineShoot=new Image("data/anim/lazer.png");
        baseShot = new Sound("data/sound/lazer.ogg");
        dieSound = new Sound("data/sound/marineDie2.ogg");
        hitSound = new Sound("data/sound/EnemyHurt3.ogg");
        // moveLeft=true; // initial movement
    }

    public void update(int delta) throws SlickException {

        dx = (float)delta*2*MOVE_SPEED ;
        dy = (float)delta*2*MOVE_SPEED ;
        float ax = dx;
        float ay = dy;

        // ==================
        // get marine health
        // ==================

        if (getShields()<=0){
            die();
            System.out.printf("marine shields =[%d]\n",getShields());
        }

        // ===================
        // got hurt animation
        // ===================
        //System.out.printf("gotHurt=[%b]\n",gotHurt);
        /*
        if (gotHurt){

            if (lastFacingDirection.equals("right")){
                hurtRight.setLooping(false);
                fallback=hurtRight;
                hurtRight.update(delta);
                if (hurtRight.isStopped()){
                    hurtRight.restart();
                    gotHurt=false;
                }

            }
         */
        /*
            if (lastFacingDirection.equals("left")){
                //System.out.println("lFD=left");
                if (hurtLeft.isStopped()){
                    System.out.println("gotHurt got false");
                    hurtLeft.restart();//setCurrentFrame(0);
                    gotHurt=false;
                }
            } 
         */
        /*
            if (lastFacingDirection.equals("left")){
                System.out.printf("marine gotHurt=[%b]\n",gotHurt);               
                hurtLeft.setLooping(false);
                fallback=hurtLeft;
                hurtLeft.update(delta);                
                if (hurtLeft.getFrame()==3){            
                    System.out.printf("anim got stoped\n");
                    hurtLeft.stop();
                    //animLimiter=false;
                    hurtLeft.restart();
                    gotHurt=false;
                }                
            }
            }
         */

        if ((int)x>(int)BlockMap.Samus.x){
            lastFacingDirection="left";
        }
        if ((int)x<(int)BlockMap.Samus.x){
            lastFacingDirection="right";
        }



        // ==================================
        // place marine at the center of fovs
        // ==================================

        fieldOfVision.setX(x-160); 
        fieldOfVision.setY(y);
        fieldOfVision2.setX(x-240); 
        fieldOfVision2.setY(y);





        // =======================================
        // checks if player is inside marine's FOV
        // =======================================


        if (fieldOfVision.intersects(BlockMap.Samus.poly)){  
            attack=true;
            //System.out.println("we entered fieldOfVision");

        }else{ attack=false;}

        if (fieldOfVision2.intersects(BlockMap.Samus.poly)){            
            //System.out.println("we entered fieldOfVision2");
            if (lastFacingDirection.equals("left")&&!attack){                
                moveLeft=true;
                moveRight=false;
            }
            if (lastFacingDirection.equals("right")&&!attack){
                moveLeft=false;
                moveRight=true;                
            }   
        }else{
            moveRight= false;
            moveLeft=false;
            fallback=marineStand;
            fallback.update(delta);
        }


        // ==================================
        // what to do if marine detect player
        // ==================================

        if (attack){	
            //System.out.println("attacking !!");
            attack(poly.getX(),poly.getY(), delta);
        }



        // =====================
        // marine movement code
        // =====================
        if (!attack){           
            if (moveRight&&!gotHurt) {
                fallback=marineRight;
                marineRight.update(delta);
                //lastFacingDirection="right";
                x += ax;
                poly.setX(x+size[0]);
                if (GameState.entityCollisionWith(this)){
                    if (diagUp){
                        y-=(getVector().getY());                
                        poly.setY(y);
                    }else{
                        x -= ax;
                        poly.setX(x);
                        moveRight=false;
                        //moveLeft=true;
                    }
                }
            }       


            if (moveLeft&&!gotHurt) {
                fallback=marineLeft;
                marineLeft.update(delta);
                //lastFacingDirection="left";
                x -= ax;
                poly.setX(x+size[0]);
                if (GameState.entityCollisionWith(this)){   
                    if (diagDown){
                        y-=(getVector().getY());                
                        poly.setY(y);
                    }else{
                        x += ax;
                        poly.setX(x);
                        moveLeft=false;
                        //moveRight=true;
                    }
                }
            }
           
            

            // ================
            // gravity system
            // ================

            if (!GameState.entityCollisionWith(this)){
                applyGravity=true;
                falling=true;
            }            

            if (applyGravity){
                y += ay;
                poly.setY(y);
                if (GameState.entityCollisionWith(this)){
                    y -= ay;
                    poly.setY(y);
                    falling=false;
                    applyGravity=false;
                }                
            }

            // ===================================
            // prevent marine to cross map borders
            // ===================================
            if (x < 50) {
                x = 50; 
                moveLeft=false; moveRight=true;
            }
            if (y < 0) y = 0;		
            if (x > BlockMap.mapWidth - 100) {
                x = BlockMap.mapWidth - 100; 
                moveRight=false; moveLeft=true;
            }
            if (y > BlockMap.mapHeight- 50) {y = BlockMap.mapHeight- 48;}
        }
        if (mustDie){
            die();
        }

/*
        if (gotHurt){
            hurtAnim.setLooping(false);
            fallbackAnim=hurtAnim;
            hurtAnim.update(delta);
            if (hurtAnim.isStopped()){
                hurtAnim.restart();
                hurtAnim.setCurrentFrame(0);
                gotHurt=false;
            }                
        }
*/




        if (gotHurt){ 
            if (!hitSound.playing())
            hitSound.play(1, Progress.sfxVol/20);
  
            setShields(shields-=10);            

            if (lastFacingDirection.equals("left")){
                fallback=hurtLeft;
                hurtLeft.update(delta); 
                gotHurt=false;
            }
            if (lastFacingDirection.equals("right")){
                fallback=hurtRight;
                hurtRight.update(delta);
                gotHurt=false;
            }            
        }

    }



    public void attack(float x, float y, long delta) throws SlickException{

        moveLeft=false;
        moveRight=false;

        if(currentShootTime < maxShootTime) {
            currentShootTime += delta;
        }
        if (lastFacingDirection.equals("left")&&!gotHurt){
            fallback=attackLeft;
            attackLeft.update( delta);
            if (nextShootOK){
                BlockMap.entities.add(new Shoot((int)x-50,(int)y+15, marineShoot,"left","bullet"));
                baseShot.play(1,Progress.sfxVol/20);
            }
        }
        if (lastFacingDirection.equals("right")&&!gotHurt){
            fallback=attackRight;
            fallback.update( delta);
            if (nextShootOK){
                BlockMap.entities.add(new Shoot((int)x+40,(int)y+15, marineShoot,"right","bullet"));
                baseShot.play(1,Progress.sfxVol/20);
            }
        }
        if (currentShootTime >= maxShootTime) {
            nextShootOK = true;
            currentShootTime = 0;
        } 
        else {
            nextShootOK = false;
        }

    }

    public void die() {
        System.out.printf("marine must die\n");
        dieSound.play(1, Progress.sfxVol/20);
        BlockMap.entities.remove(this);
    }

    public boolean isCollisionWith(LevelObject other) {
        if (other.type.equals("dDown")){
            if (poly.intersects(other.poly)){
                if (moveLeft){
                    diagDown=true;
                } 
            }else{diagDown=false;} 
        }
        if (other.type.equals("dUp")){
            if (poly.intersects(other.poly)){
                if (moveRight){
                    diagUp=true;
                }               
            }else{diagUp=false;} 
        }

        if (other.type.equals("marine")||other.type.equals("samus"))
            return false;

        if (other.type.equals("elevStart")||other.type.equals("elevStop"))
            return false;  

        return poly.intersects(other.poly);
    }

    public boolean collidedWith(LevelObject entity) {
        return true;
    }


    public void draw(Graphics g) {
        g.drawAnimation(fallback, x, y);
        if (debugMode){
            g.draw(poly);
            g.draw(fieldOfVision);
            g.draw(fieldOfVision2);
        }
    }
}
